package com.jh.storageview;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader;
import android.os.Handler;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewTreeObserver;
import android.view.animation.DecelerateInterpolator;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import java.util.ArrayList;
import java.util.List;

public class StorageView extends View{

    public static final String TAG = "StorageView";

    private List<StorageViewObserver> observers = new ArrayList<>();
    private int index = -1;

    Bitmap mBpOval1, mBpOval2, mBpRect;
    Bitmap sysBpOval, sysDataOval, docOval, pkgOval, videoOval, soundOval, imgOval, appOval;
    float sysOffset, sysDOffset, docOffset, pkgOffset, videoOffset, soundOffset, imgOffset, appOffset;
    float oldSysOffset, oldSysDOffset, oldDocOffset, oldPkgOffset, oldVideoOffset, oldSoundOffset, oldImgOffset, oldAppOffset;
    int topBOval = 65;
    int itemContentOvalHeight = 1;
    PorterDuffXfermode xfermode = new PorterDuffXfermode(PorterDuff.Mode.DST_OVER);
    Paint mPaint;
    Path mPath;
    int rootWidth;
    int rootHeight;
    float readH;

    int initAlpha = 0;
    int alphaVV = initAlpha, alphaDV = initAlpha, alphaDocV = initAlpha, alphaPkgV = initAlpha, alphaVideoV = initAlpha, alphaSoundV = initAlpha, alphaImgV = initAlpha, alphaAppV = initAlpha;

    private float sysGInitTop,sysDInitTop,docInitTop, pkgInitTop, videoInitTop, soundInitTop, imgInitTop, appInitTop;

    ValueAnimator alphaV, alphaD, alphaDoc, alphaPkg, alphaVideo, alphaSound, alphaImg, alphaApp;
    boolean shoudDrawBg = true;

    AnimatorSet asSysG = new AnimatorSet();
    AnimatorSet asSysD = new AnimatorSet();
    AnimatorSet asSysDoc = new AnimatorSet();
    AnimatorSet asSysPkg = new AnimatorSet();
    AnimatorSet asSysVideo = new AnimatorSet();
    AnimatorSet asSysSound = new AnimatorSet();
    AnimatorSet asSysImg = new AnimatorSet();
    AnimatorSet asSysApp = new AnimatorSet();

    Handler mHandler = new Handler();

    LinearGradient linearGradient;

    boolean isInAnimatorFinish;

    StorageBean mStorageBean = new StorageBean();

    Canvas mCanvas = new Canvas();
    Paint mPaint1 = new Paint();
    Paint mPaintMask;
    Canvas mCanvasMask;
    Bitmap mSysGMask, mSysDMask, mDocMask, mPkgMask, mVideoMask, mSoundMask, mImgMask, mAppMask;

    PointF mPointF = new PointF();

    public StorageView(Context context) {
        super(context);
        init();
    }

    public StorageView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public StorageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    public StorageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init();
    }

    ValueAnimator mVSysG, mVSysD, mVDoc, mVPkg, mVVideo, mVSound, mVImg, mVApp;
    private void init(){
        mPath = new Path();
        mPaint = new Paint();
        mPaintMask = new Paint();
        mPaintMask.setColor(getResources().getColor(R.color.mask, null));
        mCanvasMask = new Canvas();

        setClickable(true);

        alphaV = ValueAnimator.ofInt(0, 255);
        alphaV.setDuration(1000);
        alphaV.setInterpolator(new DecelerateInterpolator());
        alphaV.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(@NonNull ValueAnimator animation) {
                alphaVV = (int) animation.getAnimatedValue();
                invalidate();
            }
        });

        alphaD = ValueAnimator.ofInt(0, 255);
        alphaD.setDuration(1000);
        alphaD.setInterpolator(new DecelerateInterpolator());
        alphaD.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(@NonNull ValueAnimator animation) {
                alphaDV = (int) animation.getAnimatedValue();
                invalidate();
            }
        });

        alphaDoc = ValueAnimator.ofInt(0, 255);
        alphaDoc.setDuration(1000);
        alphaDoc.setInterpolator(new DecelerateInterpolator());
        alphaDoc.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(@NonNull ValueAnimator animation) {
                alphaDocV = (int) animation.getAnimatedValue();
                invalidate();
            }
        });

        alphaPkg = ValueAnimator.ofInt(0, 255);
        alphaPkg.setDuration(1000);
        alphaPkg.setInterpolator(new DecelerateInterpolator());
        alphaPkg.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(@NonNull ValueAnimator animation) {
                alphaPkgV = (int) animation.getAnimatedValue();
                invalidate();
            }
        });

        alphaVideo = ValueAnimator.ofInt(0, 255);
        alphaVideo.setDuration(1000);
        alphaVideo.setInterpolator(new DecelerateInterpolator());
        alphaVideo.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(@NonNull ValueAnimator animation) {
                alphaVideoV = (int) animation.getAnimatedValue();
                invalidate();
            }
        });

        alphaSound = ValueAnimator.ofInt(0, 255);
        alphaSound.setDuration(1000);
        alphaSound.setInterpolator(new DecelerateInterpolator());
        alphaSound.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(@NonNull ValueAnimator animation) {
                alphaSoundV = (int) animation.getAnimatedValue();
                invalidate();
            }
        });

        alphaImg = ValueAnimator.ofInt(0, 255);
        alphaImg.setDuration(1000);
        alphaImg.setInterpolator(new DecelerateInterpolator());
        alphaImg.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(@NonNull ValueAnimator animation) {
                alphaImgV = (int) animation.getAnimatedValue();
                invalidate();
            }
        });

        alphaApp = ValueAnimator.ofInt(0, 255);
        alphaApp.setDuration(1000);
        alphaApp.setInterpolator(new DecelerateInterpolator());
        alphaApp.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(@NonNull ValueAnimator animation) {
                alphaAppV = (int) animation.getAnimatedValue();
                invalidate();
            }
        });

        mVSysG = ValueAnimator.ofFloat(0, 0);
        mVSysG.setDuration(1000);
        mVSysG.setInterpolator(new DecelerateInterpolator());
        mVSysG.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(@NonNull ValueAnimator animation) {
                sysOffset = (float) animation.getAnimatedValue();
                oldSysOffset =  sysOffset;
                invalidate();
            }
        });

        mVSysD = ValueAnimator.ofFloat(0, 0);
        mVSysD.setDuration(1000);
        mVSysD.setInterpolator(new DecelerateInterpolator());
        mVSysD.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(@NonNull ValueAnimator animation) {
                sysDOffset = (float) animation.getAnimatedValue();
                oldSysDOffset = sysDOffset;
                invalidate();
            }
        });

        mVDoc = ValueAnimator.ofFloat(0, 0);
        mVDoc.setDuration(1000);
        mVDoc.setInterpolator(new DecelerateInterpolator());
        mVDoc.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(@NonNull ValueAnimator animation) {
                docOffset = (float) animation.getAnimatedValue();
                oldDocOffset = docOffset;
                invalidate();
            }
        });

        mVPkg = ValueAnimator.ofFloat(0, 0);
        mVPkg.setDuration(1000);
        mVPkg.setInterpolator(new DecelerateInterpolator());
        mVPkg.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(@NonNull ValueAnimator animation) {
                pkgOffset = (float) animation.getAnimatedValue();
                oldPkgOffset = pkgOffset;
                invalidate();
            }
        });

        mVVideo = ValueAnimator.ofFloat(0, 0);
        mVVideo.setDuration(1000);
        mVVideo.setInterpolator(new DecelerateInterpolator());
        mVVideo.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(@NonNull ValueAnimator animation) {
                videoOffset = (float) animation.getAnimatedValue();
                oldVideoOffset = videoOffset;
                invalidate();
            }
        });

        mVSound = ValueAnimator.ofFloat(0, 0);
        mVSound.setDuration(1000);
        mVSound.setInterpolator(new DecelerateInterpolator());
        mVSound.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(@NonNull ValueAnimator animation) {
                soundOffset = (float) animation.getAnimatedValue();
                oldSoundOffset = soundOffset;
                invalidate();
            }
        });

        mVImg = ValueAnimator.ofFloat(0, 0);
        mVImg.setDuration(1000);
        mVImg.setInterpolator(new DecelerateInterpolator());
        mVImg.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(@NonNull ValueAnimator animation) {
                imgOffset = (float) animation.getAnimatedValue();
                oldImgOffset = imgOffset;
                invalidate();
            }
        });

       mVApp = ValueAnimator.ofFloat(0, 0);
       mVApp.setDuration(1000);
       mVApp.setInterpolator(new DecelerateInterpolator());
       mVApp.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(@NonNull ValueAnimator animation) {
                appOffset = (float) animation.getAnimatedValue();
                oldAppOffset = appOffset;
                invalidate();
            }
        });

       getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
           @Override
           public void onGlobalLayout() {
               mSysGMask = createMaskSysG(rootWidth, rootHeight);
               mSysDMask = createMaskSysD(rootWidth, rootHeight);
               mDocMask = createMaskDoc(rootWidth, rootHeight);
               mPkgMask = createMaskPkg(rootWidth, rootHeight);
               mVideoMask = createMaskVideo(rootWidth, rootHeight);
               mSoundMask = createMaskSound(rootWidth, rootHeight);
               mImgMask = createMaskImg(rootWidth, rootHeight);
               mAppMask = createMaskApp(rootWidth, rootHeight);

               linearGradient = new LinearGradient(
                       0, 0, rootWidth, 0,   // 渐变从左到右
                       Color.parseColor("#FFFFFF"), Color.parseColor("#DFDEDE"), Shader.TileMode.CLAMP
               );

               readH =  (getHeight() - (itemContentOvalHeight+1.0f*topBOval+1.0f*topBOval/2) - (itemContentOvalHeight+1.0f*topBOval/2)*7);

               mPath.reset();
               mPath.addRect(0, 0, rootWidth, rootHeight, Path.Direction.CCW);

               // @{ 背景初始化
               mBpOval1 = createOval1(rootWidth, rootHeight);
               mBpOval2 = createOval2(rootWidth, rootHeight);
               mBpRect = createRect(rootWidth, rootHeight);
               // @}

               // @{ 内容初始化
               sysBpOval = createSysGOval(rootWidth, rootHeight);
               sysDataOval = createSysDataOval(rootWidth, rootHeight);
               docOval = createDocOval(rootWidth, rootHeight);
               pkgOval = createPkgOval(rootWidth, rootHeight);
               soundOval = createSoundOval(rootWidth, rootHeight);
               videoOval = createVideoOval(rootWidth, rootHeight);
               imgOval = createImgOval(rootWidth, rootHeight);
               appOval = createAppOval(rootWidth, rootHeight);

               // @}

               ValueAnimator sysGV = ValueAnimator.ofFloat(0,  (rootHeight-(itemContentOvalHeight + topBOval + (1.0f*topBOval/2))));
               ValueAnimator sysDV = ValueAnimator.ofFloat(0,  (rootHeight-(itemContentOvalHeight + topBOval + (1.0f*topBOval/2)) - (itemContentOvalHeight + (1.0f*topBOval/2))));
               ValueAnimator docV = ValueAnimator.ofFloat(0,  (rootHeight-(itemContentOvalHeight + topBOval + (1.0f*topBOval/2)) - (itemContentOvalHeight + (1.0f*topBOval/2))*2));
               ValueAnimator pkgV = ValueAnimator.ofFloat(0,  (rootHeight-(itemContentOvalHeight + topBOval + (1.0f*topBOval/2)) - (itemContentOvalHeight + (1.0f*topBOval/2))*3));
               ValueAnimator videoV = ValueAnimator.ofFloat(0,  (rootHeight-(itemContentOvalHeight + topBOval + (1.0f*topBOval/2)) - (itemContentOvalHeight + (1.0f*topBOval/2))*4));
               ValueAnimator soundV = ValueAnimator.ofFloat(0,  (rootHeight-(itemContentOvalHeight + topBOval + (1.0f*topBOval/2)) - (itemContentOvalHeight + (1.0f*topBOval/2))*5));
               ValueAnimator imgV = ValueAnimator.ofFloat(0,  (rootHeight-(itemContentOvalHeight + topBOval + (1.0f*topBOval/2)) - (itemContentOvalHeight + (1.0f*topBOval/2))*6));
               ValueAnimator appV = ValueAnimator.ofFloat(0,  (rootHeight-(itemContentOvalHeight + topBOval + (1.0f*topBOval/2)) - (itemContentOvalHeight + (1.0f*topBOval/2))*7));

               sysGV.setDuration(1000);
               sysGV.setInterpolator(new DecelerateInterpolator());
               sysGV.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                   @Override
                   public void onAnimationUpdate(@NonNull ValueAnimator animation) {
                       sysGInitTop = (float) animation.getAnimatedValue();
                       invalidate();
                   }
               });
        asSysG.playTogether(sysGV, alphaV);
//               asSysG.playTogether(sysGV);

               sysDV.setDuration(1000);
               sysDV.setInterpolator(new DecelerateInterpolator());
               sysDV.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                   @Override
                   public void onAnimationUpdate(@NonNull ValueAnimator animation) {
                       sysDInitTop = (float) animation.getAnimatedValue();
                       invalidate();
                   }
               });
        asSysD.playTogether(sysDV, alphaD);
//               asSysD.playTogether(sysDV);

               docV.setDuration(1000);
               docV.setInterpolator(new DecelerateInterpolator());
               docV.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                   @Override
                   public void onAnimationUpdate(@NonNull ValueAnimator animation) {
                       docInitTop = (float) animation.getAnimatedValue();
                       invalidate();
                   }
               });
        asSysDoc.playTogether(docV, alphaDoc);
//               asSysDoc.playTogether(docV);

               pkgV.setDuration(1000);
               pkgV.setInterpolator(new DecelerateInterpolator());
               pkgV.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                   @Override
                   public void onAnimationUpdate(@NonNull ValueAnimator animation) {
                       pkgInitTop = (float) animation.getAnimatedValue();
                       invalidate();
                   }
               });
        asSysPkg.playTogether(pkgV, alphaPkg);
//               asSysPkg.playTogether(pkgV);

               videoV.setDuration(1000);
               videoV.setInterpolator(new DecelerateInterpolator());
               videoV.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                   @Override
                   public void onAnimationUpdate(@NonNull ValueAnimator animation) {
                       videoInitTop = (float) animation.getAnimatedValue();
                       invalidate();
                   }
               });
        asSysVideo.playTogether(videoV, alphaVideo);
//               asSysVideo.playTogether(videoV);

               soundV.setDuration(1000);
               soundV.setInterpolator(new DecelerateInterpolator());
               soundV.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                   @Override
                   public void onAnimationUpdate(@NonNull ValueAnimator animation) {
                       soundInitTop = (float) animation.getAnimatedValue();
                       invalidate();
                   }
               });
        asSysSound.playTogether(soundV, alphaSound);
//               asSysSound.playTogether(soundV);

               imgV.setDuration(1000);
               imgV.setInterpolator(new DecelerateInterpolator());
               imgV.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                   @Override
                   public void onAnimationUpdate(@NonNull ValueAnimator animation) {
                       imgInitTop = (float) animation.getAnimatedValue();
                       invalidate();
                   }
               });
        asSysImg.playTogether(imgV, alphaImg);
//               asSysImg.playTogether(imgV);

               appV.setDuration(1000);
               appV.setInterpolator(new DecelerateInterpolator());
               appV.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                   @Override
                   public void onAnimationUpdate(@NonNull ValueAnimator animation) {
                       appInitTop = (float) animation.getAnimatedValue();
                       invalidate();
                   }
               });
        asSysApp.playTogether(appV, alphaApp);
//               asSysApp.playTogether(appV);
               asSysApp.addListener(new AnimatorListenerAdapter() {
                   @Override
                   public void onAnimationEnd(Animator animation) {
                       super.onAnimationEnd(animation);
                       isInAnimatorFinish = true;
                       updateInternalData();
                   }
               });

               int step = 80;
               mHandler.postDelayed(new Runnable() {
                   @Override
                   public void run() {
                       asSysG.start();
                   }
               }, 0);
               mHandler.postDelayed(new Runnable() {
                   @Override
                   public void run() {
                       asSysD.start();
                   }
               }, step);
               mHandler.postDelayed(new Runnable() {
                   @Override
                   public void run() {
                       asSysDoc.start();
                   }
               }, step*2);
               mHandler.postDelayed(new Runnable() {
                   @Override
                   public void run() {
                       asSysPkg.start();
                   }
               }, step*3);
               mHandler.postDelayed(new Runnable() {
                   @Override
                   public void run() {
                       asSysVideo.start();
                   }
               }, step*4);
               mHandler.postDelayed(new Runnable() {
                   @Override
                   public void run() {
                       asSysSound.start();
                   }
               }, step*5);
               mHandler.postDelayed(new Runnable() {
                   @Override
                   public void run() {
                       asSysImg.start();
                   }
               }, step*6);
               mHandler.postDelayed(new Runnable() {
                   @Override
                   public void run() {
                       asSysApp.start();
                   }
               }, step*7);
               getViewTreeObserver().removeOnGlobalLayoutListener(this);
           }
       });
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        rootWidth = getWidth();
        rootHeight = getHeight();
    }

    public void updateData(StorageBean storageBean) {
        if (storageBean == null) return;
        mStorageBean = storageBean;
        if (!isInAnimatorFinish){
            return;
        }
        updateInternalData();
    }

    private void updateInternalData() {
        sysOffset =  (1.0f*readH * mStorageBean.BeanSysOffset / 100);
        sysDOffset = (1.0f*readH * mStorageBean.BeanSysDOffset / 100);
        docOffset =  (1.0f*readH * mStorageBean.BeanDocOffset / 100);
        pkgOffset =  (1.0f*readH * mStorageBean.BeanPkgOffset / 100);
        soundOffset =  (1.0f*readH * mStorageBean.BeanSoundOffset / 100);
        videoOffset =  (1.0f*readH * mStorageBean.BeanVideoOffset / 100);
        imgOffset =  (1.0f*readH * mStorageBean.BeanImgOffset / 100);
        appOffset =  (1.0f*readH * mStorageBean.BeanAppOffset / 100);

        mVSysG.setFloatValues(oldSysOffset, sysOffset);
        mVSysD.setFloatValues(oldSysDOffset, sysDOffset);
        mVDoc.setFloatValues(oldDocOffset, docOffset);
        mVPkg.setFloatValues(oldPkgOffset, pkgOffset);
        mVSound.setFloatValues(oldSoundOffset, soundOffset);
        mVVideo.setFloatValues(oldVideoOffset, videoOffset);
        mVImg.setFloatValues(oldImgOffset, imgOffset);
        mVApp.setFloatValues(oldAppOffset, appOffset);

        mVSysG.start();
        mVSysD.start();
        mVDoc.start();
        mVPkg.start();
        mVSound.start();
        mVVideo.start();
        mVImg.start();
        mVApp.start();
    }

    /****************背景@{*********************/
    private Bitmap createOval1(int width, int height){
        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        Paint paint = new Paint();
        paint.setColor(getResources().getColor(R.color.oval1, null));
        canvas.drawOval(0, 0, width, topBOval, paint);
        return bitmap;
    }
    private Bitmap createOval2(int width, int height){
        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        Paint paint = new Paint();
        paint.setShader(linearGradient);
        canvas.drawOval(0, 0, width, topBOval, paint);
        shoudDrawBg = true;
        return bitmap;
    }

    private Bitmap createRect(int width, int height){
        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        Paint paint = new Paint();
        paint.setShader(linearGradient);
        canvas.drawRect(0, 0, width, height-topBOval, paint);
        return bitmap;
    }
    /****************背景@}*********************/

    /****************圆柱中的填充物@{*********************/
    // 系统固件
    private Bitmap createSysGOval(int width, int height){
        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        Paint paint = new Paint();
        paint.setColor(getResources().getColor(R.color.sys_gu, null));
        canvas.drawOval(0, 0, width, topBOval, paint);
        paint.setXfermode(xfermode);
        paint.setColor(getResources().getColor(R.color.sys_guR, null));
        canvas.drawRect(0, 1.0f*topBOval/2, width, itemContentOvalHeight+1.0f*topBOval + sysOffset, paint);
        paint.setXfermode(xfermode);
        paint.setColor(getResources().getColor(R.color.sys_guR, null));
        canvas.drawOval(0, itemContentOvalHeight+1.0f*topBOval/2 + sysOffset, width, itemContentOvalHeight+1.0f*topBOval+1.0f*topBOval/2 +  + sysOffset, paint);
        return bitmap;
    }
    private Bitmap reloadSysGOval(Bitmap bitmap, int width, int height){
        Canvas canvas = new Canvas(bitmap);
        canvas.drawColor(0, PorterDuff.Mode.CLEAR);
        Paint paint = new Paint();
        paint.setColor(getResources().getColor(R.color.sys_gu, null));
        canvas.drawOval(0, 0, width, topBOval, paint);
        paint.setXfermode(xfermode);
        paint.setColor(getResources().getColor(R.color.sys_guR, null));
        canvas.drawRect(0, 1.0f*topBOval/2, width, itemContentOvalHeight+1.0f*topBOval + sysOffset, paint);
        paint.setXfermode(xfermode);
        paint.setColor(getResources().getColor(R.color.sys_guR, null));
        canvas.drawOval(0, itemContentOvalHeight+1.0f*topBOval/2 + sysOffset, width, itemContentOvalHeight+1.0f*topBOval+1.0f*topBOval/2 + sysOffset, paint);
        return bitmap;
    }
    private Bitmap createMaskSysG(int width, int height){
        mSysGMask = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(mSysGMask);
        canvas.drawOval(0, 0, width, topBOval, mPaintMask);
        canvas.drawRect(0, 1.0f*topBOval/2, width, itemContentOvalHeight+1.0f*topBOval + sysOffset, mPaintMask);
        canvas.drawOval(0, itemContentOvalHeight+1.0f*topBOval/2 + sysOffset, width, itemContentOvalHeight+1.0f*topBOval+1.0f*topBOval/2 + sysOffset, mPaintMask);
        return mSysGMask;
    }
    private Bitmap reloadMaskSysG(int width, int height){
        mCanvasMask.setBitmap(mSysGMask);
        clearMask();
        mCanvasMask.drawOval(0, 0, width, topBOval, mPaintMask);
        mCanvasMask.drawRect(0, 1.0f*topBOval/2, width, itemContentOvalHeight+1.0f*topBOval + sysOffset, mPaintMask);
        mCanvasMask.drawOval(0, itemContentOvalHeight+1.0f*topBOval/2 + sysOffset, width, itemContentOvalHeight+1.0f*topBOval+1.0f*topBOval/2 + sysOffset, mPaintMask);
        return mSysGMask;
    }

    // 系统数据
    private Bitmap createSysDataOval(int width, int height){
        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        Paint paint = new Paint();
        paint.setColor(getResources().getColor(R.color.sys_data, null));
        canvas.drawOval(0, 0, width, topBOval, paint);
        paint.setXfermode(xfermode);
        paint.setColor(getResources().getColor(R.color.sys_dataR, null));
        canvas.drawRect(0, 1.0f*topBOval/2, width, itemContentOvalHeight+1.0f*topBOval + sysDOffset, paint);
        paint.setXfermode(xfermode);
        paint.setColor(getResources().getColor(R.color.sys_dataR, null));
        canvas.drawOval(0, itemContentOvalHeight+1.0f*topBOval/2 + sysDOffset, width, itemContentOvalHeight+1.0f*topBOval+1.0f*topBOval/2 + sysDOffset, paint);
        return bitmap;
    }
    private Bitmap reloadSysDataOval(Bitmap bitmap, int width, int height){
        mCanvas.setBitmap(bitmap);
        mCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
        mPaint1.setColor(getResources().getColor(R.color.sys_data, null));
        mCanvas.drawOval(0, 0, width, topBOval, mPaint1);
        mPaint1.setXfermode(xfermode);
        mPaint1.setColor(getResources().getColor(R.color.sys_dataR, null));
        mCanvas.drawRect(0, 1.0f*topBOval/2, width, itemContentOvalHeight+1.0f*topBOval + sysDOffset, mPaint1);
        mPaint1.setXfermode(xfermode);
        mPaint1.setColor(getResources().getColor(R.color.sys_dataR, null));
        mCanvas.drawOval(0, itemContentOvalHeight+1.0f*topBOval/2 + sysDOffset, width, itemContentOvalHeight+1.0f*topBOval+1.0f*topBOval/2 + sysDOffset, mPaint1);
        return bitmap;
    }
    private Bitmap createMaskSysD(int width, int height){
        mSysDMask = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(mSysDMask);
        canvas.drawOval(0, 0, width, topBOval, mPaintMask);
        canvas.drawRect(0, 1.0f*topBOval/2, width, itemContentOvalHeight+1.0f*topBOval + sysOffset, mPaintMask);
        canvas.drawOval(0, itemContentOvalHeight+1.0f*topBOval/2 + sysOffset, width, itemContentOvalHeight+1.0f*topBOval+1.0f*topBOval/2 + sysOffset, mPaintMask);
        return mSysDMask;
    }
    private Bitmap reloadMaskSysD(int width, int height){
        mCanvasMask.setBitmap(mSysDMask);
        clearMask();
        mCanvasMask.drawOval(0, 0, width, topBOval, mPaintMask);
        mCanvasMask.drawRect(0, 1.0f*topBOval/2, width, itemContentOvalHeight+1.0f*topBOval + sysOffset, mPaintMask);
        mCanvasMask.drawOval(0, itemContentOvalHeight+1.0f*topBOval/2 + sysOffset, width, itemContentOvalHeight+1.0f*topBOval+1.0f*topBOval/2 + sysOffset, mPaintMask);
        return mSysDMask;
    }

    // 文档
    private Bitmap createDocOval(int width, int height){
        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        Paint paint = new Paint();
        paint.setColor(getResources().getColor(R.color.doc, null));
        canvas.drawOval(0, 0, width, topBOval, paint);
        paint.setXfermode(xfermode);
        paint.setColor(getResources().getColor(R.color.docR, null));
        canvas.drawRect(0, 1.0f*topBOval/2, width, itemContentOvalHeight+1.0f*topBOval + docOffset, paint);
        paint.setXfermode(xfermode);
        paint.setColor(getResources().getColor(R.color.docR, null));
        canvas.drawOval(0, itemContentOvalHeight+1.0f*topBOval/2 + docOffset, width, itemContentOvalHeight+1.0f*topBOval+1.0f*topBOval/2 + docOffset, paint);
        return bitmap;
    }
    private Bitmap reloadDocOval(Bitmap bitmap, int width, int height){
        Canvas canvas = new Canvas(bitmap);
        canvas.drawColor(0, PorterDuff.Mode.CLEAR);
        Paint paint = new Paint();
        paint.setColor(getResources().getColor(R.color.doc, null));
        canvas.drawOval(0, 0, width, topBOval, paint);
        paint.setXfermode(xfermode);
        paint.setColor(getResources().getColor(R.color.docR, null));
        canvas.drawRect(0, 1.0f*topBOval/2, width, itemContentOvalHeight+1.0f*topBOval + docOffset, paint);
        paint.setXfermode(xfermode);
        paint.setColor(getResources().getColor(R.color.docR, null));
        canvas.drawOval(0, itemContentOvalHeight+1.0f*topBOval/2 + docOffset, width, itemContentOvalHeight+1.0f*topBOval+1.0f*topBOval/2 + docOffset, paint);
        return bitmap;
    }
    private Bitmap createMaskDoc(int width, int height){
        mDocMask = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(mDocMask);
        canvas.drawOval(0, 0, width, topBOval, mPaintMask);
        canvas.drawRect(0, 1.0f*topBOval/2, width, itemContentOvalHeight+1.0f*topBOval + docOffset, mPaintMask);
        canvas.drawOval(0, itemContentOvalHeight+1.0f*topBOval/2 + docOffset, width, itemContentOvalHeight+1.0f*topBOval+1.0f*topBOval/2 + docOffset, mPaintMask);
        return mDocMask;
    }
    private Bitmap reloadMaskDoc(int width, int height){
        mCanvasMask.setBitmap(mDocMask);
        clearMask();
        mCanvasMask.drawOval(0, 0, width, topBOval, mPaintMask);
        mCanvasMask.drawRect(0, 1.0f*topBOval/2, width, itemContentOvalHeight+1.0f*topBOval + docOffset, mPaintMask);
        mCanvasMask.drawOval(0, itemContentOvalHeight+1.0f*topBOval/2 + docOffset, width, itemContentOvalHeight+1.0f*topBOval+1.0f*topBOval/2 + docOffset, mPaintMask);
        return mDocMask;
    }

    // 安装包
    private Bitmap createPkgOval(int width, int height){
        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        Paint paint = new Paint();
        paint.setColor(getResources().getColor(R.color.pkg, null));
        canvas.drawOval(0, 0, width, topBOval, paint);
        paint.setXfermode(xfermode);
        paint.setColor(getResources().getColor(R.color.pkgR, null));
        canvas.drawRect(0, 1.0f*topBOval/2, width, itemContentOvalHeight+1.0f*topBOval + pkgOffset, paint);
        paint.setXfermode(xfermode);
        paint.setColor(getResources().getColor(R.color.pkgR, null));
        canvas.drawOval(0, itemContentOvalHeight+1.0f*topBOval/2 + pkgOffset, width, itemContentOvalHeight+1.0f*topBOval+1.0f*topBOval/2 + pkgOffset, paint);
        return bitmap;
    }
    private Bitmap reloadPkgOval(Bitmap bitmap, int width, int height){
        mCanvas.setBitmap(bitmap);
        mCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
        mPaint1.setColor(getResources().getColor(R.color.pkg, null));
        mCanvas.drawOval(0, 0, width, topBOval, mPaint1);
        mPaint1.setXfermode(xfermode);
        mPaint1.setColor(getResources().getColor(R.color.pkgR, null));
        mCanvas.drawRect(0, 1.0f*topBOval/2, width, itemContentOvalHeight+1.0f*topBOval + pkgOffset, mPaint1);
        mPaint1.setXfermode(xfermode);
        mPaint1.setColor(getResources().getColor(R.color.pkgR, null));
        mCanvas.drawOval(0, itemContentOvalHeight+1.0f*topBOval/2 + pkgOffset, width, itemContentOvalHeight+1.0f*topBOval+1.0f*topBOval/2 + pkgOffset, mPaint1);
        return bitmap;
    }
    private Bitmap createMaskPkg(int width, int height){
        mPkgMask = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(mPkgMask);
        canvas.drawOval(0, 0, width, topBOval, mPaintMask);
        canvas.drawRect(0, 1.0f*topBOval/2, width, itemContentOvalHeight+1.0f*topBOval + pkgOffset, mPaintMask);
        canvas.drawOval(0, itemContentOvalHeight+1.0f*topBOval/2 + pkgOffset, width, itemContentOvalHeight+1.0f*topBOval+1.0f*topBOval/2 + pkgOffset, mPaintMask);
        return mPkgMask;
    }
    private Bitmap reloadMaskPkg(int width, int height){
        mCanvasMask.setBitmap(mPkgMask);
        clearMask();
        mCanvasMask.drawOval(0, 0, width, topBOval, mPaintMask);
        mCanvasMask.drawRect(0, 1.0f*topBOval/2, width, itemContentOvalHeight+1.0f*topBOval + pkgOffset, mPaintMask);
        mCanvasMask.drawOval(0, itemContentOvalHeight+1.0f*topBOval/2 + pkgOffset, width, itemContentOvalHeight+1.0f*topBOval+1.0f*topBOval/2 + pkgOffset, mPaintMask);
        return mPkgMask;
    }

    // 视频
    private Bitmap createVideoOval(int width, int height){
        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        Paint paint = new Paint();
        paint.setColor(getResources().getColor(R.color.video, null));
        canvas.drawOval(0, 0, width, topBOval, paint);
        paint.setXfermode(xfermode);
        paint.setColor(getResources().getColor(R.color.videoR, null));
        canvas.drawRect(0, 1.0f*topBOval/2, width, itemContentOvalHeight+1.0f*topBOval + videoOffset, paint);
        paint.setXfermode(xfermode);
        paint.setColor(getResources().getColor(R.color.videoR, null));
        canvas.drawOval(0, itemContentOvalHeight+1.0f*topBOval/2 + videoOffset, width, itemContentOvalHeight+1.0f*topBOval+1.0f*topBOval/2 + videoOffset, paint);
        return bitmap;
    }
    private Bitmap reloadVideoOval(Bitmap bitmap, int width, int height){
        mCanvas.setBitmap(bitmap);
        mCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
        mPaint1.setColor(getResources().getColor(R.color.video, null));
        mCanvas.drawOval(0, 0, width, topBOval, mPaint1);
        mPaint1.setXfermode(xfermode);
        mPaint1.setColor(getResources().getColor(R.color.videoR, null));
        mCanvas.drawRect(0, 1.0f*topBOval/2, width, itemContentOvalHeight+1.0f*topBOval + videoOffset, mPaint1);
        mPaint1.setXfermode(xfermode);
        mPaint1.setColor(getResources().getColor(R.color.videoR, null));
        mCanvas.drawOval(0, itemContentOvalHeight+1.0f*topBOval/2 + videoOffset, width, itemContentOvalHeight+1.0f*topBOval+1.0f*topBOval/2 + videoOffset, mPaint1);
        return bitmap;
    }
    private Bitmap createMaskVideo(int width, int height){
        mVideoMask = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(mVideoMask);
        canvas.drawOval(0, 0, width, topBOval, mPaintMask);
        canvas.drawRect(0, 1.0f*topBOval/2, width, itemContentOvalHeight+1.0f*topBOval + videoOffset, mPaintMask);
        canvas.drawOval(0, itemContentOvalHeight+1.0f*topBOval/2 + videoOffset, width, itemContentOvalHeight+1.0f*topBOval+1.0f*topBOval/2 + videoOffset, mPaintMask);
        return mVideoMask;
    }
    private Bitmap reloadMaskVideo(int width, int height){
        mCanvasMask.setBitmap(mVideoMask);
        clearMask();
        mCanvasMask.drawOval(0, 0, width, topBOval, mPaintMask);
        mCanvasMask.drawRect(0, 1.0f*topBOval/2, width, itemContentOvalHeight+1.0f*topBOval + videoOffset, mPaintMask);
        mCanvasMask.drawOval(0, itemContentOvalHeight+1.0f*topBOval/2 + videoOffset, width, itemContentOvalHeight+1.0f*topBOval+1.0f*topBOval/2 + videoOffset, mPaintMask);
        return mVideoMask;
    }


    // 音频
    private Bitmap createSoundOval(int width, int height){
        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        Paint paint = new Paint();
        paint.setColor(getResources().getColor(R.color.sound, null));
        canvas.drawOval(0, 0, width, topBOval, paint);
        paint.setXfermode(xfermode);
        paint.setColor(getResources().getColor(R.color.soundR, null));
        canvas.drawRect(0, 1.0f*topBOval/2, width, itemContentOvalHeight+1.0f*topBOval + soundOffset, paint);
        paint.setXfermode(xfermode);
        paint.setColor(getResources().getColor(R.color.soundR, null));
        canvas.drawOval(0, itemContentOvalHeight+1.0f*topBOval/2 + soundOffset, width, itemContentOvalHeight+1.0f*topBOval+1.0f*topBOval/2 + soundOffset, paint);
        return bitmap;
    }
    private Bitmap reloadSoundOval(Bitmap bitmap, int width, int height){
        mCanvas.setBitmap(bitmap);
        mCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
        mPaint1.setColor(getResources().getColor(R.color.sound, null));
        mCanvas.drawOval(0, 0, width, topBOval, mPaint1);
        mPaint1.setXfermode(xfermode);
        mPaint1.setColor(getResources().getColor(R.color.soundR, null));
        mCanvas.drawRect(0, 1.0f*topBOval/2, width, itemContentOvalHeight+1.0f*topBOval + soundOffset, mPaint1);
        mPaint1.setXfermode(xfermode);
        mPaint1.setColor(getResources().getColor(R.color.soundR, null));
        mCanvas.drawOval(0, itemContentOvalHeight+1.0f*topBOval/2 + soundOffset, width, itemContentOvalHeight+1.0f*topBOval+1.0f*topBOval/2 + soundOffset, mPaint1);
        return bitmap;
    }
    private Bitmap createMaskSound(int width, int height){
        mSoundMask = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(mSoundMask);
        canvas.drawOval(0, 0, width, topBOval, mPaintMask);
        canvas.drawRect(0, 1.0f*topBOval/2, width, itemContentOvalHeight+1.0f*topBOval + soundOffset, mPaintMask);
        canvas.drawOval(0, itemContentOvalHeight+1.0f*topBOval/2 + soundOffset, width, itemContentOvalHeight+1.0f*topBOval+1.0f*topBOval/2 + soundOffset, mPaintMask);
        return mSoundMask;
    }
    private Bitmap reloadMaskSound(int width, int height){
        mCanvasMask.setBitmap(mSoundMask);
        clearMask();
        mCanvasMask.drawOval(0, 0, width, topBOval, mPaintMask);
        mCanvasMask.drawRect(0, 1.0f*topBOval/2, width, itemContentOvalHeight+1.0f*topBOval + soundOffset, mPaintMask);
        mCanvasMask.drawOval(0, itemContentOvalHeight+1.0f*topBOval/2 + soundOffset, width, itemContentOvalHeight+1.0f*topBOval+1.0f*topBOval/2 + soundOffset, mPaintMask);
        return mSoundMask;
    }

    // 图片
    private Bitmap createImgOval(int width, int height){
        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        Paint paint = new Paint();
        paint.setColor(getResources().getColor(R.color.img, null));
        canvas.drawOval(0, 0, width, topBOval, paint);
        paint.setXfermode(xfermode);
        paint.setColor(getResources().getColor(R.color.imgR, null));
        canvas.drawRect(0, 1.0f*topBOval/2, width, itemContentOvalHeight+1.0f*topBOval + imgOffset, paint);
        paint.setXfermode(xfermode);
        paint.setColor(getResources().getColor(R.color.imgR, null));
        canvas.drawOval(0, itemContentOvalHeight+1.0f*topBOval/2 + imgOffset, width, itemContentOvalHeight+1.0f*topBOval+1.0f*topBOval/2 + imgOffset, paint);
        return bitmap;
    }
    private Bitmap reloadImgOval(Bitmap bitmap, int width, int height){
        mCanvas.setBitmap(bitmap);
        mCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
        mPaint1.setColor(getResources().getColor(R.color.img, null));
        mCanvas.drawOval(0, 0, width, topBOval, mPaint1);
        mPaint1.setXfermode(xfermode);
        mPaint1.setColor(getResources().getColor(R.color.imgR, null));
        mCanvas.drawRect(0, 1.0f*topBOval/2, width, itemContentOvalHeight+1.0f*topBOval + imgOffset, mPaint1);
        mPaint1.setXfermode(xfermode);
        mPaint1.setColor(getResources().getColor(R.color.imgR, null));
        mCanvas.drawOval(0, itemContentOvalHeight+1.0f*topBOval/2 + imgOffset, width, itemContentOvalHeight+1.0f*topBOval+1.0f*topBOval/2 + imgOffset, mPaint1);
        return bitmap;
    }
    private Bitmap createMaskImg(int width, int height){
        mImgMask = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(mImgMask);
        canvas.drawOval(0, 0, width, topBOval, mPaintMask);
        canvas.drawRect(0, 1.0f*topBOval/2, width, itemContentOvalHeight+1.0f*topBOval + imgOffset, mPaintMask);
        canvas.drawOval(0, itemContentOvalHeight+1.0f*topBOval/2 + imgOffset, width, itemContentOvalHeight+1.0f*topBOval+1.0f*topBOval/2 + imgOffset, mPaintMask);
        return mImgMask;
    }
    private Bitmap reloadMaskImg(int width, int height){
        mCanvasMask.setBitmap(mImgMask);
        clearMask();
        mCanvasMask.drawOval(0, 0, width, topBOval, mPaintMask);
        mCanvasMask.drawRect(0, 1.0f*topBOval/2, width, itemContentOvalHeight+1.0f*topBOval + imgOffset, mPaintMask);
        mCanvasMask.drawOval(0, itemContentOvalHeight+1.0f*topBOval/2 + imgOffset, width, itemContentOvalHeight+1.0f*topBOval+1.0f*topBOval/2 + imgOffset, mPaintMask);
        return mImgMask;
    }

    // app
    private Bitmap createAppOval(int width, int height){
        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        Paint paint = new Paint();
        paint.setColor(getResources().getColor(R.color.app, null));
        canvas.drawOval(0, 0, width, topBOval, paint);
        paint.setXfermode(xfermode);
        paint.setColor(getResources().getColor(R.color.appR, null));
        canvas.drawRect(0, 1.0f*topBOval/2, width, itemContentOvalHeight+1.0f*topBOval + appOffset, paint);
        paint.setXfermode(xfermode);
        paint.setColor(getResources().getColor(R.color.appR, null));
        canvas.drawOval(0, itemContentOvalHeight+1.0f*topBOval/2 + appOffset, width, itemContentOvalHeight+1.0f*topBOval+1.0f*topBOval/2 + appOffset, paint);
        return bitmap;
    }
    private Bitmap reloadAppOval(Bitmap bitmap, int width, int height){
        mCanvas.setBitmap(bitmap);
        mCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
        mPaint1.setColor(getResources().getColor(R.color.app, null));
        mCanvas.drawOval(0, 0, width, topBOval, mPaint1);
        mPaint1.setXfermode(xfermode);
        mPaint1.setColor(getResources().getColor(R.color.appR, null));
        mCanvas.drawRect(0, 1.0f*topBOval/2, width, itemContentOvalHeight+1.0f*topBOval + appOffset, mPaint1);
        mPaint1.setXfermode(xfermode);
        mPaint1.setColor(getResources().getColor(R.color.appR, null));
        mCanvas.drawOval(0, itemContentOvalHeight+1.0f*topBOval/2 + appOffset, width, itemContentOvalHeight+1.0f*topBOval+1.0f*topBOval/2 + appOffset, mPaint1);
        mPaint1.setXfermode(null);
        return bitmap;
    }
    private Bitmap createMaskApp(int width, int height){
        mAppMask = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        mCanvasMask = new Canvas(mAppMask);
        mCanvasMask.drawOval(0, 0, width, topBOval, mPaintMask);
        mCanvasMask.drawRect(0, 1.0f*topBOval/2, width, itemContentOvalHeight+1.0f*topBOval + appOffset, mPaintMask);
        mCanvasMask.drawOval(0, itemContentOvalHeight+1.0f*topBOval/2 + appOffset, width, itemContentOvalHeight+1.0f*topBOval+1.0f*topBOval/2 + appOffset, mPaintMask);
        return mAppMask;
    }
    private Bitmap reloadMaskApp(int width, int height){
        mCanvasMask.setBitmap(mAppMask);
        clearMask();
        mCanvasMask.drawOval(0, 0, width, topBOval, mPaintMask);
        mCanvasMask.drawRect(0, 1.0f*topBOval/2, width, itemContentOvalHeight+1.0f*topBOval + appOffset, mPaintMask);
        mCanvasMask.drawOval(0, itemContentOvalHeight+1.0f*topBOval/2 + appOffset, width, itemContentOvalHeight+1.0f*topBOval+1.0f*topBOval/2 + appOffset, mPaintMask);
        return mAppMask;
    }
    private void clearMask(){
        mCanvasMask.drawColor(0, PorterDuff.Mode.CLEAR);
    }

    /****************圆柱中的填充物@}*********************/

    @Override
    protected void onDraw(@NonNull Canvas canvas) {
        super.onDraw(canvas);
        int count = canvas.saveLayer(0, 0, rootWidth, rootHeight, mPaint);
        if (shoudDrawBg){
            // @{画背景
            canvas.drawBitmap(mBpOval1, 0, 0, mPaint);
            mPaint.setXfermode(xfermode);
            canvas.drawBitmap(mBpRect, 0, 1.0f*topBOval/2, mPaint);
            canvas.drawBitmap(mBpOval2, 0, rootHeight-topBOval, mPaint);
            // @}

            mPaint.setXfermode(null);
        }

        if ( sysBpOval==null || sysBpOval == sysDataOval || docOval == null || pkgOval == null
                ||videoOval == null || soundOval == null || imgOval == null || appOval == null)return;
        // @{ 画内容
        //if (oldSysOffset != sysOffset){
        //    oldSysOffset = sysOffset;
        //    sysBpOval = reloadSysGOval(sysBpOval, rootWidth, rootHeight);
        //}
        sysBpOval = reloadSysGOval(sysBpOval, rootWidth, rootHeight);

        //if (oldSysDOffset != sysDOffset){
        //    oldSysDOffset = sysDOffset;
        //    sysDataOval = reloadSysDataOval(sysDataOval, rootWidth, rootHeight);
        //}
        sysDataOval = reloadSysDataOval(sysDataOval, rootWidth, rootHeight);

        //if (oldDocOffset != docOffset){
        //    oldDocOffset = docOffset;
        //    docOval = reloadDocOval(docOval, rootWidth, rootHeight);
        //}
        docOval = reloadDocOval(docOval, rootWidth, rootHeight);

        //if (oldPkgOffset != pkgOffset){
        //    oldPkgOffset = pkgOffset;
        //    pkgOval = reloadPkgOval(pkgOval, rootWidth, rootHeight);
        //}
        pkgOval = reloadPkgOval(pkgOval, rootWidth, rootHeight);

        //if (oldSoundOffset != soundOffset){
        //    oldSoundOffset = soundOffset;
        //    soundOval = reloadSoundOval(soundOval, rootWidth, rootHeight);
        //}
        soundOval = reloadSoundOval(soundOval, rootWidth, rootHeight);

        //if (oldImgOffset != imgOffset){
        //    oldImgOffset = imgOffset;
        //    imgOval = reloadImgOval(imgOval, rootWidth, rootHeight);
        //}
        imgOval = reloadImgOval(imgOval, rootWidth, rootHeight);

        //if (oldVideoOffset != videoOffset){
        //    oldVideoOffset = videoOffset;
        //    videoOval = reloadVideoOval(videoOval, rootWidth, rootHeight);
        //}
        videoOval = reloadVideoOval(videoOval, rootWidth, rootHeight);

        //if (oldAppOffset != appOffset){
        //    oldAppOffset = appOffset;
        //    appOval = reloadAppOval(appOval, rootWidth, rootHeight);
        //}
        appOval = reloadAppOval(appOval, rootWidth, rootHeight);

        float mSysGOvalHeight = (itemContentOvalHeight+1.0f*topBOval + sysOffset) - 1.0f*topBOval/2 + topBOval;
        float mSysDOvalHeight = (itemContentOvalHeight+1.0f*topBOval + sysDOffset) - 1.0f*topBOval/2 + topBOval;
        float mDocOvalHeight = (itemContentOvalHeight+1.0f*topBOval + docOffset) - 1.0f*topBOval/2 + topBOval;
        float mPkgOvalHeight = (itemContentOvalHeight+1.0f*topBOval + pkgOffset) - 1.0f*topBOval/2 + topBOval;
        float mVideoOvalHeight = (itemContentOvalHeight+1.0f*topBOval + videoOffset) - 1.0f*topBOval/2 + topBOval;
        float mSoundOvalHeight = (itemContentOvalHeight+1.0f*topBOval + soundOffset) - 1.0f*topBOval/2 + topBOval;
        float mImgOvalHeight = (itemContentOvalHeight+1.0f*topBOval + imgOffset) - 1.0f*topBOval/2 + topBOval;
        float mAppOvalHeight = (itemContentOvalHeight+1.0f*topBOval + appOffset) - 1.0f*topBOval/2 + topBOval;
        mSysGRect.left = 0;
        mSysGRect.top = sysGInitTop - sysOffset + topBOval;
        mSysGRect.right = rootWidth;
        mSysGRect.bottom = sysGInitTop - sysOffset + mSysGOvalHeight;

        mSysDRect.left = 0;
        mSysDRect.top = sysDInitTop - sysOffset - sysDOffset + topBOval;
        mSysDRect.right = rootWidth;
        mSysDRect.bottom = sysDInitTop - sysOffset - sysDOffset + mSysDOvalHeight;

        mDocRect.left = 0;
        mDocRect.top = docInitTop - sysOffset - sysDOffset - docOffset + topBOval;
        mDocRect.right = rootWidth;
        mDocRect.bottom = docInitTop - sysOffset - sysDOffset - docOffset + mDocOvalHeight;

        mPkgRect.left = 0;
        mPkgRect.top = pkgInitTop - sysOffset - sysDOffset - docOffset - pkgOffset + topBOval;
        mPkgRect.right = rootWidth;
        mPkgRect.bottom = pkgInitTop - sysOffset - sysDOffset - docOffset - pkgOffset + mPkgOvalHeight;

        mVideoRect.left = 0;
        mVideoRect.top = videoInitTop - sysOffset - sysDOffset - docOffset - pkgOffset - videoOffset + topBOval;
        mVideoRect.right = rootWidth;
        mVideoRect.bottom = videoInitTop - sysOffset - sysDOffset - docOffset - pkgOffset - videoOffset + mVideoOvalHeight;

        mSoundRect.left = 0;
        mSoundRect.top = soundInitTop - sysOffset - sysDOffset - docOffset - pkgOffset - videoOffset - soundOffset + topBOval;
        mSoundRect.right = rootWidth;
        mSoundRect.bottom = soundInitTop - sysOffset - sysDOffset - docOffset - pkgOffset - videoOffset - soundOffset + mSoundOvalHeight;

        //img范围
        mImgRect.left = 0;
        mImgRect.top = imgInitTop - sysOffset - sysDOffset - docOffset - pkgOffset - videoOffset - soundOffset - imgOffset + topBOval;
        mImgRect.right = rootWidth;
        mImgRect.bottom = imgInitTop - sysOffset - sysDOffset - docOffset - pkgOffset - videoOffset - soundOffset - imgOffset + mImgOvalHeight;

        // app 范围
        mAppRect.left = 0;
        mAppRect.top = appInitTop - sysOffset - sysDOffset - docOffset - pkgOffset - videoOffset - soundOffset - imgOffset - appOffset;
        mAppRect.right = rootWidth;
        mAppRect.bottom = appInitTop - sysOffset - sysDOffset - docOffset - pkgOffset - videoOffset - soundOffset - imgOffset - appOffset + mAppOvalHeight;
        // @}

        mPaint.setAlpha(alphaVV);
        canvas.drawBitmap(sysBpOval, 0, sysGInitTop - sysOffset, mPaint);

        mPointF.set(0f, 0f);

        //更新固件遮罩图
        if (isTouchRect) {
            mSysGMask = reloadMaskSysG(rootWidth, rootHeight);
            if (!isSysGTouch) {
                mPaint.setAlpha(200);
                canvas.drawBitmap(mSysGMask, 0, sysGInitTop - sysOffset, mPaint);
                mPaint.setAlpha(255);
            } else {
                clearMask();
                canvas.drawBitmap(mSysGMask, 0, sysGInitTop - sysOffset, mPaint);
                mPointF.set(rootWidth, mSysGRect.top + mSysGRect.height()/2 - 1.0f*topBOval/2);
            }
        }

        mPaint.setAlpha(alphaDV);
        canvas.drawBitmap(sysDataOval, 0, sysDInitTop - sysOffset - sysDOffset, mPaint);

        //更新视频遮罩图
        if (isTouchRect) {
            mSysDMask = reloadMaskSysD(rootWidth, rootHeight);
            if (!isSysDTouch) {
                mPaint.setAlpha(200);
                canvas.drawBitmap(mSysDMask, 0, sysDInitTop - sysOffset - sysDOffset, mPaint);
                mPaint.setAlpha(255);
            } else {
                clearMask();
                canvas.drawBitmap(mSysDMask, 0, sysDInitTop - sysOffset - sysDOffset, mPaint);
                mPointF.set(rootWidth, mSysDRect.top + mSysDRect.height()/2 - 1.0f*topBOval/2);
            }
        }

        mPaint.setAlpha(alphaDocV);
        canvas.drawBitmap(docOval, 0,  docInitTop - sysOffset - sysDOffset - docOffset, mPaint);

        //更新视频遮罩图
        if (isTouchRect) {
            mDocMask = reloadMaskDoc(rootWidth, rootHeight);
            if (!isDocTouck) {
                mPaint.setAlpha(200);
                canvas.drawBitmap(mDocMask, 0, docInitTop - sysOffset - sysDOffset - docOffset, mPaint);
                mPaint.setAlpha(255);
            } else {
                clearMask();
                canvas.drawBitmap(mDocMask, 0, docInitTop - sysOffset - sysDOffset - docOffset, mPaint);
                mPointF.set(rootWidth, mDocRect.top + mDocRect.height()/2 - 1.0f*topBOval/2);
            }
        }

        mPaint.setAlpha(alphaPkgV);
        canvas.drawBitmap(pkgOval, 0,  pkgInitTop - sysOffset - sysDOffset - docOffset - pkgOffset, mPaint);

        //更新视频遮罩图
        if (isTouchRect) {
            mPkgMask = reloadMaskPkg(rootWidth, rootHeight);
            if (!isPkgTouch) {
                mPaint.setAlpha(200);
                canvas.drawBitmap(mPkgMask, 0, pkgInitTop - sysOffset - sysDOffset - docOffset - pkgOffset, mPaint);
                mPaint.setAlpha(255);
            } else {
                clearMask();
                canvas.drawBitmap(mPkgMask, 0, pkgInitTop - sysOffset - sysDOffset - docOffset - pkgOffset, mPaint);
                mPointF.set(rootWidth, mPkgRect.top + mPkgRect.height()/2 - 1.0f*topBOval/2);
            }
        }

        mPaint.setAlpha(alphaVideoV);
        canvas.drawBitmap(videoOval, 0,  videoInitTop - sysOffset - sysDOffset - docOffset - pkgOffset - videoOffset, mPaint);

        //更新视频遮罩图
        if (isTouchRect) {
            mVideoMask = reloadMaskVideo(rootWidth, rootHeight);
            if (!isVideoTouch) {
                mPaint.setAlpha(200);
                canvas.drawBitmap(mVideoMask, 0, videoInitTop - sysOffset - sysDOffset - docOffset - pkgOffset - videoOffset, mPaint);
                mPaint.setAlpha(255);
            } else {
                clearMask();
                canvas.drawBitmap(mVideoMask, 0, videoInitTop - sysOffset - sysDOffset - docOffset - pkgOffset - videoOffset, mPaint);
                mPointF.set(rootWidth, mVideoRect.top + mVideoRect.height()/2 - 1.0f*topBOval/2);
            }
        }

        mPaint.setAlpha(alphaSoundV);
        canvas.drawBitmap(soundOval, 0,  soundInitTop - sysOffset - sysDOffset - docOffset - pkgOffset - videoOffset - soundOffset, mPaint);

        //更新声音遮罩图
        if (isTouchRect) {
            mSoundMask = reloadMaskSound(rootWidth, rootHeight);
            if (!isSoundTouch) {
                mPaint.setAlpha(200);
                canvas.drawBitmap(mSoundMask, 0, soundInitTop - sysOffset - sysDOffset - docOffset - pkgOffset - videoOffset - soundOffset, mPaint);
                mPaint.setAlpha(255);
            } else {
                clearMask();
                canvas.drawBitmap(mSoundMask, 0, soundInitTop - sysOffset - sysDOffset - docOffset - pkgOffset - videoOffset - soundOffset, mPaint);
                mPointF.set(rootWidth, mSoundRect.top + mSoundRect.height()/2 - 1.0f*topBOval/2);
            }
        }

        mPaint.setAlpha(alphaImgV);
        canvas.drawBitmap(imgOval, 0,  imgInitTop - sysOffset - sysDOffset - docOffset - pkgOffset - videoOffset - soundOffset - imgOffset, mPaint);

        //更新图片遮罩图
        if (isTouchRect){
            mImgMask = reloadMaskImg(rootWidth, rootHeight);
            if (!isImgTouch){
                mPaint.setAlpha(200);
                canvas.drawBitmap(mImgMask, 0,  imgInitTop - sysOffset - sysDOffset - docOffset - pkgOffset - videoOffset - soundOffset - imgOffset, mPaint);
                mPaint.setAlpha(255);
            }else{
                clearMask();
                canvas.drawBitmap(mImgMask, 0,  imgInitTop - sysOffset - sysDOffset - docOffset - pkgOffset - videoOffset - soundOffset - imgOffset, mPaint);
                mPointF.set(rootWidth, mImgRect.top + mImgRect.height()/2 - 1.0f*topBOval/2);
            }
        }


        mPaint.setAlpha(alphaAppV);
        canvas.drawBitmap(appOval, 0,  appInitTop - sysOffset - sysDOffset - docOffset - pkgOffset - videoOffset - soundOffset - imgOffset - appOffset, mPaint);
        mPaint.setAlpha(255);

        //更新应用遮罩图
        if (isTouchRect){
            mAppMask = reloadMaskApp(rootWidth, rootHeight);
            if (!isAppTouch){
                mPaint.setAlpha(200);
                canvas.drawBitmap(mAppMask, 0,  appInitTop - sysOffset - sysDOffset - docOffset - pkgOffset - videoOffset - soundOffset - imgOffset - appOffset, mPaint);
                mPaint.setAlpha(255);
            }else{
                clearMask();
                canvas.drawBitmap(mAppMask, 0,  appInitTop - sysOffset - sysDOffset - docOffset - pkgOffset - videoOffset - soundOffset - imgOffset - appOffset, mPaint);
                mPointF.set(rootWidth, mAppRect.top + mAppRect.height()/2 - 1.0f*topBOval/2);
            }
        }

        if (mTouchOvalListener != null){
            mTouchOvalListener.pointCall(mPointF);
        }

//        Paint paint = new Paint();
//        paint.setStyle(Paint.Style.STROKE);
//        paint.setColor(getResources().getColor(R.color.mask, null));
//        canvas.drawRect(mAppRect, paint);
//        canvas.restore();

    }

    boolean isSysGTouch, isSysDTouch, isDocTouck, isPkgTouch, isVideoTouch, isSoundTouch, isImgTouch, isAppTouch ;
    boolean isTouchRect;
    RectF mSysGRect = new RectF();
    RectF mSysDRect = new RectF();
    RectF mDocRect = new RectF();
    RectF mPkgRect = new RectF();
    RectF mVideoRect = new RectF();
    RectF mSoundRect = new RectF();
    RectF mImgRect = new RectF();
    RectF mAppRect = new RectF();
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        isSysGTouch = mSysGRect.contains(event.getX(), event.getY());
        isSysDTouch = mSysDRect.contains(event.getX(), event.getY());
        isDocTouck = mDocRect.contains(event.getX(), event.getY());
        isPkgTouch = mPkgRect.contains(event.getX(), event.getY());
        isVideoTouch = mVideoRect.contains(event.getX(), event.getY());
        isSoundTouch = mSoundRect.contains(event.getX(), event.getY());
        isImgTouch = mImgRect.contains(event.getX(), event.getY());
        isAppTouch = mAppRect.contains(event.getX(), event.getY());
        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:
            case MotionEvent.ACTION_MOVE:
                if (isSysGTouch
                ||isSysDTouch
                ||isDocTouck
                ||isPkgTouch
                ||isVideoTouch
                ||isSoundTouch
                ||isImgTouch
                ||isAppTouch
                ){
                    isTouchRect = true;
                    invalidate();
                    if (mTouchOvalListener != null){
                        boolean[] aar = new boolean[]{
                                isSysGTouch,
                                isSysDTouch,
                                isDocTouck,
                                isPkgTouch,
                                isVideoTouch,
                                isSoundTouch,
                                isImgTouch,
                                isAppTouch
                        };
                        mTouchOvalListener.callback(aar);
                        for (int i = 0; i < aar.length; i++) {
                            if (aar[i]){
                                index = i;
                                updateAll();
                                break;
                            }
                        }
                    }
                }
                break;
            case MotionEvent.ACTION_UP:
                isSysGTouch = false;
                isSysDTouch = false;
                isDocTouck = false;
                isPkgTouch = false;
                isVideoTouch = false;
                isSoundTouch = false;
                isImgTouch = false;
                isAppTouch = false;
                isTouchRect = false;
                invalidate();
                if (mTouchOvalListener != null){
                    mTouchOvalListener.touchUp();
                }
                index = -1;
                updateAll();
                break;
        }
        return super.onTouchEvent(event);
    }

    private TouchOvalListener mTouchOvalListener;

    public interface TouchOvalListener{
        void callback(boolean[] touchOval);
        void pointCall(PointF pointF);
        void touchUp();
    }

    public void setTouchOvalListener(TouchOvalListener listener){
        mTouchOvalListener = listener;
    }

    public void addObserver(StorageViewObserver observer){
        observers.add(observer);
    }

    public void removeObserver(StorageViewObserver observer){
        observers.remove(observer);
    }

    public void updateAll(){
        for (StorageViewObserver observer : observers) {
            observer.update(index);
        }
    }

}
